{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 线性回归的方程规范解\n",
    "\n",
    "在网站上给出的公式有问题，正确的公式应该是\n",
    "\n",
    "$$\n",
    "Y = X  \\times theta\n",
    "$$\n",
    "\n",
    "其中，X.shape = (m,n+1)，theta.shape=(n+1,1)，Y.shape=(m,1)。对于每个样本都增加了一个维度，值为1，相当于$w_0=1$，这样就相当于把偏差b放到了矩阵中，不用单独计算。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#encoding=utf8 \n",
    "import numpy as np\n",
    "def mse_score(y_predict,y_test):\n",
    "    '''\n",
    "    input:y_predict(ndarray):预测值\n",
    "          y_test(ndarray):真实值\n",
    "    ouput:mse(float):mse损失函数值\n",
    "    '''\n",
    "    #********* Begin *********#\n",
    "    mse = np.mean((y_predict - y_test)**2)\n",
    "    #********* End *********#\n",
    "    return mse\n",
    "\n",
    "class LinearRegression :\n",
    "    def __init__(self):\n",
    "        '''初始化线性回归模型'''\n",
    "        self.theta = None\n",
    "    def fit_normal(self,train_data,train_label):\n",
    "        '''\n",
    "        input:train_data(ndarray):训练样本\n",
    "              train_label(ndarray):训练标签\n",
    "        '''\n",
    "        #********* Begin *********#\n",
    "        # train_data--m行n列，需要转换成m行，n+1列，第一列是全1\n",
    "        m = len(train_data)\n",
    "        one = np.ones([m, 1])\n",
    "        X = np.hstack((one, train_data))\n",
    "        # theta是(n+1)*1的向量\n",
    "        self.theta = np.dot(np.dot(np.linalg.inv(np.dot(X.T, X)), X.T), train_label)\n",
    "\n",
    "        #********* End *********#\n",
    "        return self.theta\n",
    "    def predict(self,test_data):\n",
    "        '''\n",
    "        input:test_data(ndarray):测试样本\n",
    "        '''\n",
    "        #********* Begin *********#\n",
    "        m = len(test_data)\n",
    "        one = np.ones([m, 1])\n",
    "        X = np.hstack((one, test_data))\n",
    "        return np.dot(X, self.theta)\n",
    "        #********* End *********#"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 衡量线性回归的性能指标"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#encoding=utf8 \n",
    "import numpy as np\n",
    "#mse\n",
    "def mse_score(y_predict,y_test):\n",
    "    mse = np.mean((y_predict-y_test)**2)\n",
    "    return mse\n",
    "#r2\n",
    "def r2_score(y_predict,y_test):\n",
    "    '''\n",
    "    input:y_predict(ndarray):预测值\n",
    "          y_test(ndarray):真实值\n",
    "    output:r2(float):r2值\n",
    "    '''\n",
    "    #********* Begin *********#\n",
    "    fenzi = np.sum((y_predict - y_test)**2)\n",
    "    if fenzi == 0:\n",
    "        r2 = 1\n",
    "    else :\n",
    "        fenmu = np.sum((np.mean(y_test)-y_test)**2)\n",
    "        r2 = 1 - fenzi/fenmu\n",
    "    #********* End *********#\n",
    "    return r2\n",
    "\n",
    "class LinearRegression :\n",
    "    def __init__(self):\n",
    "        '''初始化线性回归模型'''\n",
    "        self.theta = None\n",
    "    def fit_normal(self,train_data,train_label):\n",
    "        '''\n",
    "        input:train_data(ndarray):训练样本\n",
    "              train_label(ndarray):训练标签\n",
    "        '''\n",
    "        #********* Begin *********#\n",
    "        # train_data--m行n列，需要转换成m行，n+1列，第一列是全1\n",
    "        m = len(train_data)\n",
    "        one = np.ones([m, 1])\n",
    "        X = np.hstack((one, train_data))\n",
    "        # theta是(n+1)*1的向量\n",
    "        self.theta = np.dot(np.dot(np.linalg.inv(np.dot(X.T, X)), X.T), train_label)\n",
    "\n",
    "        #********* End *********#\n",
    "        return self.theta\n",
    "    def predict(self,test_data):\n",
    "        '''\n",
    "        input:test_data(ndarray):测试样本\n",
    "        '''\n",
    "        #********* Begin *********#\n",
    "        m = len(test_data)\n",
    "        one = np.ones([m, 1])\n",
    "        X = np.hstack((one, test_data))\n",
    "        return np.dot(X, self.theta)\n",
    "        #********* End *********#"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# scikit-learn线性回归实践--波士顿房价预测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "from sklearn.linear_model import LinearRegression\n",
    "import numpy as np\n",
    "\n",
    "#获取训练数据\n",
    "train_data = pd.read_csv('./step3/train_data.csv')\n",
    "#获取训练标签\n",
    "train_label = pd.read_csv('./step3/train_label.csv')\n",
    "train_label = train_label['target']\n",
    "#获取测试数据\n",
    "test_data = pd.read_csv('./step3/test_data.csv')\n",
    "\n",
    "# 将dataframe格式转换为numpy\n",
    "X_train = np.array(train_data)\n",
    "Y_train = np.array(train_label)\n",
    "X_test = np.array(test_data)\n",
    "\n",
    "lr = LinearRegression()\n",
    "lr.fit(X_train, Y_train)\n",
    "predict = lr.predict(X_test)\n",
    "\n",
    "res = pd.DataFrame(predict, columns=['result'])\n",
    "res.to_csv('./step3/result.csv')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "tf38",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
